# Copyright (C) 2006, 2007  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

#
# For more information: http://carrierclass.net/
#
use strict; use warnings;

package CCNProxy::Provision::Application::openser;
use base qw(CCNProxy::Provision::Base);

# The AVPs used by our application or other OpenSER modules.

our %avps = (
    # Used by the UAC module
    uac_realm       => 10,
    uac_user        => 11,
    uac_pass        => 12,
    # Used by nathelper, etc.
    nathelper       => 42,
    rpid            => 150,
    # Our application-specifc AVPs
    tgw             => 151,
    ttype           => 152,
    gwadv           => 153,
    local_npanxx    => 160,
    premium_npa     => 161,
    premium_nxx     => 162,
    from_user       => 170,
    default_npa     => 171,
    numuser         => 172,
    cfa             => 175, 
    cfnr            => 176,
    cfb             => 177,
    cfda            => 178,
    src_type        => 180,
    dst_type        => 181,
    allow_local     => 190,
    allow_premium   => 191,
    allow_ld        => 192,
    allow_intl      => 193,
);

use CCN::Text;
use CCNCore::Scripting;
use CCNCore::Home;

sub run()
{
    my $self = shift;
    return if $self->p->force_manager;

    $self->PACKAGE('openser');
    $self->PACKAGE('openser-mysql-module'); # At least on Debian..

    # Accounting location
    my $accounting_dir = '/var/log/openser';
    if($self->upgrading || ! -d $accounting_dir )
    {
        CCN::Scripting::exec_command(qq(mkdir -p "$accounting_dir" \&\& chown openser "$accounting_dir"));
    }

    # Should OpenSER be enabled?
    return $self->disable('openser') unless defined $self->px_member;

    $self->enable('openser');

    # Generate openser.cfg
    
    my $SALT = $self->system_salt;

    my ($pxy_db_cluster,$dbname) = $self->sql_get(q(SELECT db_cluster, db_name FROM proxy_cluster WHERE id = ).$self->px_member);

    my @pxy_db_servers = $self->sql_get_array(q(SELECT id FROM server WHERE db_member = ?),$pxy_db_cluster);

    return $self->error ("openser: has a database been selected for proxy cluster ".$self->px_member." ?")
        if $#pxy_db_servers < 0;

    # TBD Need better server selection algorithm.
    #     (Actually, need SER to support multiple database servers and failover.)
    my $pxy_db_server = $pxy_db_servers[0];
    $pxy_db_server = $self->p->server_pk
        if grep { $_ eq $self->p->server_pk } @pxy_db_servers;
    my $pxy_db_server_ip = $self->get_replication_ip_of($pxy_db_server);

    # See db_ser.pm
    my $password = $self->make_password(${pxy_db_cluster},${SALT},$self->p->server_pk,'openser');

    our %openser_values = (
        PROXY_CLUSTER      => $self->p->{px_member},
        PROXY_IP           => $self->get_realtime_ip_of($self->p->server_pk),
        DB_URL             => "mysql://openser:$password\@$pxy_db_server_ip/$dbname",
        DEFAULT_EXPIRE     => 90,
        MIN_EXPIRE         => 60,
        MAX_EXPIRE         => 120, # in seconds; 0 = do not check
        CHALLENGE          => 'ccn@'.$self->system_domain,
        USE_DOMAIN_UL      => 0, # USRLOC
        USE_DOMAIN_OTHER   => 0,
        DOMAIN_TABLE       => 'domain',
        AVP_ALIASES        => join(';',map { $_."=I:".$avps{$_} } (keys %avps)),
    );


    my $config = content_of(CCNCore::Home::manager.'/lib/CCNProxy/templates/openser.cfg');

    # Substitute ${variable} in the template ser.cfg code.
    $config =~ s/\$\{(\w+)\}/exists($openser_values{$1}) ? defined($openser_values{$1}) ? $openser_values{$1} : die("Undefined OpenSER value $1 ") : die("Unexistent OpenSER value $1")/ge;

    if( $self->p->operating_system =~ /debian|ccn/ )
    {
        foreach('/etc/default/openser')
        {
            CAT $_, <<'CONF';
RUN_OPENSER=yes
USER=openser
GROUP=openser
MEMORY=64
DUMP_CORE=no
CONF
            CCNProxy::Scripting::IF_CHANGED_restart_openser($_);
        }
    }

    foreach('/etc/openser/openser.cfg')
    {
        CAT $_, $config;
        CCNProxy::Scripting::IF_CHANGED_restart_openser($_);
    }
}

1;